#!/usr/bin/python3
import sys
# sys.path.append('/home/oect')
import codecs
import csv
import os
import re
import shutil
import json
import subprocess
from typing import Iterable
from src.config import constant
from src.libs.logger import logger
from src.libs.executecmd import ExecuteCmd

class Command:
    """
    dnf/osc相关命令的执行
    """
    def __init__(self, path=None) -> None:
        # package = package
        self._save_path = '/root/temprpmbuild'
        if not os.path.exists(self._save_path):
            os.makedirs(self._save_path, exist_ok=True)
        
    def download(self, package):
        """dnf下载源码包"""
        cmd_result = subprocess.run(
            args=["dnf", "download", package, "--source"],
            shell=False,
            cwd=self._save_path,
        )
        return cmd_result.returncode == 0

    def _unrpm(self, package, del_source=True):
        cmd_result = subprocess.run(
            args=["unrpm", package + "*.src.rpm"], shell=False, cwd=self._save_path
        )
        if del_source and cmd_result.returncode == 0:
            os.system(
                "rm -rf %s" % os.path.join(self._save_path, package + "*.src.rpm")
            )
        return os.listdir(self._save_path)

    def _osc_project(self, project, project_path, clean=True, package=None):
        if clean:
            content = '<project name="%s"></project>' % project
        else:
            content = """
                    <project name="{project}">
                        <package name="{package}" state="A" />
                    </project>
            """.format(
                project=project, package=package
            )
        if not os.path.exists(project_path + "/.osc/_packages"):
            raise FileNotFoundError("project dictory not found ")
        with open(project_path + "/.osc/_packages", "w", encoding="utf-8") as file:
            file.write(content)

    def osc_remove(self, project_path, files):
        dest_path = os.path.join('/root/', project_path)
        logger.info(dest_path)
        if not os.path.exists(dest_path):
            subprocess.run(args=["osc", "co", project_path], shell=False, cwd='/root/')
        
        subprocess.run(args=["osc", "update"], shell=False, cwd=dest_path)
        
        for file in files:
            subprocess.run(args=["cp", "-rf", file, dest_path], shell=False)

        subprocess.run(args=["osc", "addremove"], shell=False, cwd=dest_path)
        subprocess.run(args=["osc", "ci", "-n"], shell=False, cwd=dest_path)


    def pull_obs_project(self, project, path):
        """拉取特定的工程"""
        cmd_result = subprocess.run(args=["osc", "co", project], shell=False, cwd=path)
        return cmd_result.returncode == 0

    @classmethod
    def provides_bin_source(cls, provide):
        """
        获取组件对应的源码包
        """
        dnf_query_bin = ["dnf", "repoquery", "--whatprovides", provide]
        cmd_ouput = ExecuteCmd.cmd_output(dnf_query_bin)
        binary_name = 'NA'
        if cmd_ouput is None:
            logger.warning("No result of cmd:%s", dnf_query_bin)
            binary_name = provide
        else:
            data = cmd_ouput.split("\n")
            for line in data:
                logger.info(line)
                if 'Last metadata expiration check' in line or not line:
                    continue
                else:
                    binary_name = line.rsplit('-', 2)[0]
                    break

        if not binary_name:
            logger.info("No bin/src_name info for :%s", provide)
            return '', ''
        else:

            logger.info("query bin_name:%s", binary_name)
            src_name = cls.binary_source(binary_name)
            
            logger.info("query src_name:%s", src_name)

        return binary_name, src_name

    @classmethod
    def binary_source(cls, binary_package):
        """
        获取二进制对应的源码包名
        """
        src_name = 'NA'
        dnf_query_src = f"dnf repoquery --source {binary_package}"
        logger.info(dnf_query_src)
        cmd_ouput = ExecuteCmd.cmd_output(dnf_query_src.split())
        if  cmd_ouput is None:
            logger.error(f"{dnf_query_src} failed")
            return src_name
        
        data = cmd_ouput.split("\n")

        for line in data:
            if 'src.rpm' in line:
                src_name = line.rsplit('-', 2)[0]
                break

        logger.info("query src_name:%s", src_name)
        return src_name

    @classmethod
    def provides_binary(cls, provides):
        """
        获取provides对应的二进制包名
        """
        binary_name = 'NA'
        dnf_query_bin = f"dnf repoquery --whatprovides {provides}"
        logger.info(dnf_query_bin)
        cmd_ouput = ExecuteCmd.cmd_output(dnf_query_bin.split())
        if  cmd_ouput is None:
            logger.error(f"{dnf_query_bin} failed")
            return binary_name
        
        data = cmd_ouput.split("\n")
        for line in data:
            if '.oe1' in line:
                binary_name = line.rsplit('-', 2)[0]
                break

        logger.info("query bin_name:%s", binary_name)
        return binary_name
        

    @staticmethod
    def wget(folder, url):
        """
        通过wget下载
        """
        os.system("wget -P %s -nc %s" % (folder, url))
    
    @classmethod
    def get_rpms_2_compare(cls, pkg):
        """
        @description :Get the list of packages to compare
        -----------
        @param : pkg
        -----------
        @returns :
        -----------
        """
        query_rpm_requires = "rpm -pq --requires --nosignature {pkgpath}/{rpm}"
        query_rpm_provides = "rpm -pq --provides --nosignature {pkgpath}/{rpm}"
        old_rpm_path = "/home/21.09-bin"
        new_rpm_path = "/home/22.03-bin"
        ls_new_cmd = f"ls {new_rpm_path}"
        ls_new_out = ExecuteCmd.cmd_output(ls_new_cmd.split())
        if  ls_new_out is None:
            logger.warning("No new rpms")
            return True
        new_data = ls_new_out.split("\n")
        new_rpms = []
        for line in new_data:
            if '.rpm' in line and '.src.rpm' not in line:
                new_rpms.append(line)
        
        logger.info(new_rpms)

        for rpm in new_rpms:
            query_new_rpm_requires = query_rpm_requires.format(pkgpath = new_rpm_path, rpm = rpm)
            query_old_rpm_requires = query_rpm_requires.format(pkgpath = old_rpm_path, rpm = rpm)
            query_new_rpm_provides = query_rpm_provides.format(pkgpath = new_rpm_path, rpm = rpm)
            query_old_rpm_provides = query_rpm_provides.format(pkgpath = old_rpm_path, rpm = rpm)

            query_new_requires_out = ExecuteCmd.cmd_output(query_new_rpm_requires.split())
            query_old_requires_out = ExecuteCmd.cmd_output(query_old_rpm_requires.split())
            query_new_provides_out = ExecuteCmd.cmd_output(query_new_rpm_provides.split())
            query_old_provides_out = ExecuteCmd.cmd_output(query_old_rpm_provides.split())

            if  query_new_requires_out is None or query_old_requires_out is None or \
                query_new_provides_out is None or query_old_provides_out is None:
                logger.error(f" query {rpm} requires/provides failed")
                return False
            
            new_requires_data = query_new_requires_out.split("\n")
            old_requires_data = query_old_requires_out.split("\n")
            requires_difference = set(new_requires_data).symmetric_difference(set(old_requires_data))

            new_provides_data = query_new_provides_out.split("\n")
            old_provides_data = query_old_provides_out.split("\n")
            provides_difference = set(new_provides_data).symmetric_difference(set(old_provides_data))

            if  requires_difference is None and provides_difference is None:
                continue
            elif requires_difference is not None:
                logger.info(f"requires of {rpm} different :[{requires_difference}]")
                return False
            else:
                logger.info(f"provides of {rpm} different :[{provides_difference}]")
                return False

        logger.info(f"Both of requires/provides of {pkg} rpms are same!")
        return True